package com.zte.claa.inficombo.csa.app.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//import sun.misc.BASE64Decoder;
//import sun.misc.BASE64Encoder;

public class SecurityUtil {
	private static final Logger logger = LoggerFactory.getLogger(SecurityUtil.class);
	
	// AES-128 加密/解密key的种子. AES128_DEF_SEED_STR.BYTE[] = AES128_DEF_SEEDS;
	public static final String AES128_DEF_SEED_STR = "ZTEClaa2017_xwfd";
	public static final byte[] AES128_DEF_SEEDS = new byte[]{90,84,69,67,108,97,97,50,48,49,55,95,120,119,102,100};
	// 和AMS约定，不能随意调整IV的值（UTF-8编码）.
	private static final String AES128_CBC_IV = "0000000000000000";

	// 
	static Cipher eCipher = null;

	static Cipher dCipher = null;

	static byte[] bkey = null;

	static byte[] biv = null;

	static AlgorithmParameterSpec paramSpec = null;
	// static BASE64Decoder base64Decoder = new BASE64Decoder();
	static org.apache.commons.codec.binary.Base64 apacheBase64 = new org.apache.commons.codec.binary.Base64();
	
	static SecretKey keySpec = null;

	static String encoding = "UTF-8";

	static {
		try {
			eCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
			dCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
			// bkey = base64Decoder.decodeBuffer("SivnBF2z0IY=");
			// biv = base64Decoder.decodeBuffer("uK1EBgjPTr0=");
			bkey = apacheBase64.decode("SivnBF2z0IY=");
			biv = apacheBase64.decode("uK1EBgjPTr0=");

			paramSpec = new IvParameterSpec(biv);
			keySpec = new SecretKeySpec(bkey, "DES");

			dCipher.init(2, keySpec, paramSpec);
			eCipher.init(1, keySpec, paramSpec);
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
	}

	// ------------------DES加密--主要用于iBoss系统自身用户的口令加密---------------------//
	/**
	 * 主要用于iBoss系统自身用户的口令加密.
	 * 
	 * @param paramString
	 * @return
	 */
	public static String decrypt(String paramString) {
		try {
			byte[] arrayOfByte = null;
			synchronized (dCipher) {
				// arrayOfByte = dCipher.doFinal(base64Decoder.decodeBuffer(paramString));
				arrayOfByte = dCipher.doFinal(apacheBase64.decode(paramString));
			}
			return new String(arrayOfByte, encoding);
		} catch (Exception localException) {
			logger.error(localException.getLocalizedMessage());
			return "";
		}
	}

	/**
	 * 主要用于iBoss系统自身用户的口令解密
	 * 
	 * @param paramString
	 * @return
	 */
	public static String encrypt(String paramString) {
		try {
			byte[] arrayOfByte = null;
			synchronized (eCipher) {
				arrayOfByte = eCipher.doFinal(paramString.getBytes(encoding));
			}
			// String obj = new BASE64Encoder().encode(arrayOfByte);
			String obj = apacheBase64.encodeAsString(arrayOfByte);
			return obj;
		} catch (Exception localException) {
			logger.error(localException.getMessage());
			localException.printStackTrace();
			return "";
		}
	}
	
	// -----------byte---十六进制字符串公共转换方法------------//
	/** 
     * 将二进制转换成16进制 
     * @method parseByte2HexStr 
     * @param buf 
     * @return 
     * @throws  
     * @since v1.0 
     */  
    public static String parseByte2HexStr(byte buf[]){  
        StringBuffer sb = new StringBuffer();  
        for(int i = 0; i < buf.length; i++){  
            String hex = Integer.toHexString(buf[i] & 0xFF);  
            if (hex.length() == 1) {  
                hex = '0' + hex;  
            }  
            sb.append(hex.toUpperCase());  
        }  
        return sb.toString();  
    }  
      
    /** 
     * 将16进制转换为二进制 
     * @method parseHexStr2Byte 
     * @param hexStr 
     * @return 
     * @throws  
     * @since v1.0 
     */  
    public static byte[] parseHexStr2Byte(String hexStr){  
        if(hexStr.length() < 1)  
            return null;  
        byte[] result = new byte[hexStr.length()/2];  
        for (int i = 0;i< hexStr.length()/2; i++) {  
            int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);  
            int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);  
            result[i] = (byte) (high * 16 + low);  
        }  
        return result;  
    }  
	
	// -------------普通MD5摘要算法--用于mote/gw的导入信息完整性认证，和AMS保持一致   ---------------------//
	/**
	 * 将UTF-8编码格式的字符串转换为byte[]，然后计算其MD5摘要信息，最后按16进制字符串保存.
	 * 
	 * @param orgData
	 * @return
	 */
	public static String MD5(String orgData) {
		if (orgData == null) {
			return "";
		}
		String md5Data = orgData;
		try {
			byte[] utf8ByteArr = orgData.getBytes("UTF-8");
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(utf8ByteArr);
			byte[] enByteArr = md.digest();
			md5Data = parseByte2HexStr(enByteArr);
		} catch (Exception e) {
			logger.error("get MD5 for str failed: " + orgData, e);
		}
		return md5Data;
	}	
	
	// ------------- 主要用于mote表中appkey和nwkkey的加密与解密 -------------------------------//
	/**
	 * AES-CBC-PKCS5Padding加密算法（使用默认seeds）
	 * 
	 * @param sContent -- 待加密明文.
	 * @return 加密结果将byte转成了十六进制字符串.
	 * @throws Exception 
	 */
	public static String AESCbcEncrypt(String sContent) throws Exception {
		SecretKeySpec skeySpec = new SecretKeySpec(AES128_DEF_SEEDS, "AES");
		// "算法/模式/PKCS5Padding补码方式"， Nopadding
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		//使用CBC模式，需要一个向量iv，可增加加密算法的强度
		IvParameterSpec iv = new IvParameterSpec(AES128_CBC_IV.getBytes("UTF-8"));
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
		byte[] encrypted = cipher.doFinal(sContent.getBytes("UTF-8"));
		// 16进制字符串输出。
		return parseByte2HexStr(encrypted);
	}

    /**
     * AES-CBC-PKCS5Padding解密算法（使用默认seeds）
     * 
     * @param sEncryptContent -- 加密后的密文，加密结果byte[]转为十六进制字符串格式.
     * @return 解密后的明文.
     * @throws Exception
     */
	public static String AESCbcDecrypt(String sEncryptContent) throws Exception {
		SecretKeySpec skeySpec = new SecretKeySpec(AES128_DEF_SEEDS, "AES");
		// "算法/模式/PKCS5Padding补码方式"， Nopadding
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		// 使用CBC模式，需要一个向量iv，可增加加密算法的强度
		IvParameterSpec iv = new IvParameterSpec(AES128_CBC_IV.getBytes("UTF-8"));
		cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
		// 和加密对应，先将密文16进制字符串转换成byte[]
		byte[] encrypted = parseHexStr2Byte(sEncryptContent);
		byte[] original = cipher.doFinal(encrypted);
		return new String(original, "UTF-8");
	}
	
	// -------------普通 AES加密，用于mote/gw的导入信息的加密和解密, 和infi-AMS加密解密算法保存一致   ----------------//
	/**
	 * AES-CBC-PKCS5Padding加密算法
	 * 
	 * @param sKey -- AES加密种子，16个字符的UTF-8编码格式字符串.
	 * @param sContent -- 待加密明文.
	 * @return 加密结果将byte转成了十六进制字符串.
	 * @throws Exception 
	 */
	public static String AES128_CBC_PKCS5Pad_Encrypt(String sKey, String sContent) throws Exception {
		// sKey必须是16个字符长度的字符串(utf-8编码格式）
		if (sKey == null || sKey.length() != 16) {
			logger.warn("Key is invalid: " + sKey);
			return null;
		}
		byte[] raw = sKey.getBytes("UTF-8");
		SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
		// "算法/模式/PKCS5Padding补码方式"， Nopadding
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		//使用CBC模式，需要一个向量iv，可增加加密算法的强度
		IvParameterSpec iv = new IvParameterSpec(AES128_CBC_IV.getBytes("UTF-8"));
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
		byte[] encrypted = cipher.doFinal(sContent.getBytes("UTF-8"));
		// 16进制字符串输出。
		return parseByte2HexStr(encrypted);
	}

    /**
     * AES-CBC-PKCS5Padding解密算法
     * 
     * @param sKey -- AES加密种子，16个字符的UTF-8编码格式字符串.
     * @param sEncryptContent -- 加密后的密文，加密结果byte[]转为十六进制字符串格式.
     * @return 解密后的明文.
     * @throws Exception
     */
	public static String AES128_CBC_PKCS5Pad_Decrypt(String sKey, String sEncryptContent) throws Exception {
		// sKey必须是16个字符长度的字符串(utf-8编码格式）
		if (sKey == null || sKey.length() != 16) {
			logger.warn("Key is invalid: " + sKey);
			return null;
		}
		byte[] raw = sKey.getBytes("UTF-8");
		SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
		// "算法/模式/PKCS5Padding补码方式"， Nopadding
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		// 使用CBC模式，需要一个向量iv，可增加加密算法的强度
		IvParameterSpec iv = new IvParameterSpec(AES128_CBC_IV.getBytes("UTF-8"));
		cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
		// 和加密对应，先将密文16进制字符串转换成byte[]
		byte[] encrypted = parseHexStr2Byte(sEncryptContent);
		byte[] original = cipher.doFinal(encrypted);
		return new String(original, "UTF-8");
	}
	
	/**
	 * 文本文件读取
	 * 
	 * @param fileName
	 */
	public static String readFile(String filePath) {
		InputStream in = null;  
		StringBuffer buf = new StringBuffer();
		try {
			File file = new File(filePath);
			if (!file.exists()) {
				return "";
			}
			in = new FileInputStream(file);  
            byte[] bs = new byte[1024];
            int rn = 0;
            while ((rn = in.read(bs)) != -1) {  
            	// 这里需要按实际读取到的byte[]来处理。
            	byte[] realBs = new byte[rn];
            	System.arraycopy(bs, 0, realBs, 0, rn);
                buf.append(new String(realBs, "UTF-8"));
            } 
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (IOException e) {
			}
		}
		return buf.toString();
	}  
	
	/**
	 * 文本文件保存
	 * 
	 * @param filePath
	 */
	public static void writeFile(String content, String filePath) {  		  
		FileWriter writer = null;  
        try {  
        	String tmpPath = filePath.replaceAll("\\\\", "/");
        	int index = tmpPath.lastIndexOf("/");
        	if(index >= 0){
        		File dir = new File(tmpPath.substring(0, index));
        		if(!dir.exists()){
        			dir.mkdirs();
        		}
        	}
        	writer = new FileWriter(filePath, false);  
            writer.write(content);      
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                if (writer != null) {  
                	writer.close();  
                }  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
	
	/**
	 * AES-128-CBC-PKCS5Pad加密文件
	 * 
	 * @param srcFilePath -- 待加密的源文件
	 * @param destFilePath -- 加密后的目标文件
	 */
	public static void encryptFileViaAESCBCPKCS5(String srcFilePath, String destFilePath){
		try{
			String content = readFile(srcFilePath);
			String encryptRet = AES128_CBC_PKCS5Pad_Encrypt(AES128_DEF_SEED_STR,content);
			writeFile(encryptRet, destFilePath);
			logger.info("AES128_ECB_PKCS5Pad_Encrypt file ok: "+destFilePath);
		}catch(Exception e){
			logger.error("AES128_ECB_PKCS5Pad_Encrypt file failed: "+srcFilePath, e);
		}
	}
	
	/**
	 * AES-128-CBC-PKCS5Pad解密文件
	 * 
	 * @param srcFilePath -- 待解密的源文件
	 * @param destFilePath -- 解密后的目标文件
	 */
	public static void decryptFileViaAESCBCPKCS5(String srcFilePath, String destFilePath){
		try{
			String content = readFile(srcFilePath);
			String decryptRet = AES128_CBC_PKCS5Pad_Decrypt(AES128_DEF_SEED_STR,content);
			writeFile(decryptRet, destFilePath);
			logger.info("AES128_ECB_PKCS5Pad_Decrypt file ok: "+destFilePath);
		}catch(Exception e){
			logger.error("AES128_ECB_PKCS5Pad_Decrypt file failed: "+srcFilePath, e);
		}
	}		
	
	// ------------  AES-CMAC 加密/解密（专用于Boss和NS/AS/JS之间的appKey/trnsKey ------------//
	/**
	 * 加密  
	 * 注：目前暂时只能处理
	 * @param sSrc，待加密字符串，通常是appKey或trnsKey，nwkKey等
	 *        格式要求 ----> 32个16进制字符组成的字符串，如：AABBCCDDEEFF99112233445566778800
	 * @param sKey，加密用的KI键值，ki_val
	 *        格式要求 ----> 32个16进制字符组成的字符串，如：AABBCCDDEEFF00112233445566778899
	 * @param xEUI，appEUI或moteEUI
	 *        格式要求 ----> 16个16进制字符串，如：AA00112233445566；
	 * @param kiID, ki键值序号，
	 *        格式要求 ----> 16进制字符串（0~65535对应的16进制字符串：0~FFFF）。, String xEUI, String hexKiID
	 * @return
	 * @throws Exception
	 */
	public static String Encrypt_AES_CMAC16(String hexSrc, String hexKey, String xEUI, String hexKiID) throws Exception {
		if(hexSrc == null || hexSrc.length() != 32){
			logger.error("Invalid src string(it should be 32 hex-chars): "+hexSrc+", EUI="+xEUI);
			throw new Exception("Invalid src string(it should be 32 hex-chars): "+hexSrc+", \nEUI="+xEUI);
		}
		if(hexKey == null || hexKey.length() != 32){
			logger.error("Invalid KI value(it should be 32 hex-chars): "+hexKey+", Kiid="+hexKiID+", EUI="+xEUI);
			throw new Exception("Invalid KI value(it should be 32 hex-chars): "+hexKey+", \nKiid="+hexKiID+", \nEUI="+xEUI);
		}
		if(xEUI == null || xEUI.trim().equals("")){
			logger.error("xEUI format is invalid(it should be 16 hex-chars): "+xEUI);
			throw new Exception("Invalid xEUI(it should be 16 hex-chars): "+xEUI);
		}
		if(hexKiID == null || hexKiID.trim().equals("")){
			logger.error("Invalid kiid(it should be 0~FFFF max 4 hex-chars): "+hexKiID+", EUI="+xEUI);
			throw new Exception("Invalid kiid(it should be 0~FFFF max 4 hex-chars): "+hexKiID+", \nEUI="+xEUI);
		}
		
		//e.g. xEUI = "0200000000001211"; hexKiID = "11223344";
    	byte[] input = AesCmac.genUpdateBytes(xEUI, hexKiID);    	
    	
    	// hexKey = "12345678901234561234567890123456";
        // 需要加密的字串
        // hexSrc =  "908711dd739c44e89f87b98f3b9c4557"; 
        logger.info("hexSrc = "+hexSrc);
        logger.info("hexKey = "+hexKey);
		byte[] masterKey = AesCmac.parseHexStr2Byte(hexKey);
		AesCmac mac = new AesCmac();
	    SecretKey key = new SecretKeySpec(masterKey, "AES");
	    mac.init(key, Cipher.ENCRYPT_MODE);  //set master key
	    mac.updateBlock(input); //given input
	    byte[] ret = mac.doFinal();		    
	    logger.info("After dofinal:\n"+AesCmac.parseByte2HexStr(ret));	
	    byte[] sSrcBs = parseHexStr2Byte(hexSrc);
	    // 如下处理是Lora NS/AS/JS特有的加密逻辑和要求.
	    byte[] encodeRet = new byte[16];
	    for (int i=0; i<16; i++)
		{
	    	encodeRet[i] = (byte)(sSrcBs[i]^ret[i]);
		}
	    logger.info("After encrypt:\n"+AesCmac.parseByte2HexStr(encodeRet));		    
	    return AesCmac.parseByte2HexStr(encodeRet);
	}

	/**
	 * 解密
	 * @param sSrc
	 * @param sKey  ----> 32个16进制字符组成的字符串.
	 * @return
	 * @throws Exception
	 */
	public static String Decrypt_AES_CMAC16(String hexSrc, String hexKey, String xEUI, String hexKiID) throws Exception {
		// 再次加密就是解密》
		return Encrypt_AES_CMAC16(hexSrc, hexKey, xEUI, hexKiID);
	}

    // -------------3DES-ECB/CBC加密/解密 -------------------- //
    /** 
     * ECB加密,不要IV 
     * @param key 密钥 
     * @param data 明文 
     * @return 密文 
     * @throws Exception 
     */  
    public static byte[] des3EncodeECB(byte[] key, byte[] data) throws Exception {  
        Key deskey = null;  
        DESedeKeySpec spec = new DESedeKeySpec(key);  
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");  
        deskey = keyfactory.generateSecret(spec);  
        Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");  
        cipher.init(Cipher.ENCRYPT_MODE, deskey);  
        byte[] bOut = cipher.doFinal(data);  
        return bOut;  
    }  
    
    /** 
     * ECB解密,不要IV 
     * @param key 密钥 
     * @param data 密文 
     * @return 明文 
     * @throws Exception 
     */  
    public static byte[] des3DecodeECB(byte[] key, byte[] data) throws Exception {  
        Key deskey = null;  
        DESedeKeySpec spec = new DESedeKeySpec(key);  
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");  
        deskey = keyfactory.generateSecret(spec);  
        Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");  
        cipher.init(Cipher.DECRYPT_MODE, deskey);  
        byte[] bOut = cipher.doFinal(data);  
        return bOut;  
    }  
    /** 
     * CBC加密 
     * @param key 密钥 
     * @param keyiv IV 
     * @param data 明文 
     * @return 密文 
     * @throws Exception 
     */  
    public static byte[] des3EncodeCBC(byte[] key, byte[] keyiv, byte[] data) throws Exception {  
        Key deskey = null;  
        DESedeKeySpec spec = new DESedeKeySpec(key);  
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");  
        deskey = keyfactory.generateSecret(spec);  
        Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding");  
        IvParameterSpec ips = new IvParameterSpec(keyiv);  
        cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);  
        byte[] bOut = cipher.doFinal(data);  
        return bOut;  
    }  
    /** 
     * CBC解密 
     * @param key 密钥 
     * @param keyiv IV 
     * @param data 密文 
     * @return 明文 
     * @throws Exception 
     */  
    public static byte[] des3DecodeCBC(byte[] key, byte[] keyiv, byte[] data) throws Exception {  
        Key deskey = null;  
        DESedeKeySpec spec = new DESedeKeySpec(key);  
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");  
        deskey = keyfactory.generateSecret(spec);  
        Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding");  
        IvParameterSpec ips = new IvParameterSpec(keyiv);  
        cipher.init(Cipher.DECRYPT_MODE, deskey, ips);  
        byte[] bOut = cipher.doFinal(data);  
        return bOut;  
    }  
    
    // --------------SHA-256摘要算法-----------------//
	public static String SHA256Digest(String str, boolean upperCase) throws Exception {
		MessageDigest messageDigest;
		String encodeStr = "";
		try {
			messageDigest = MessageDigest.getInstance("SHA-256");
			messageDigest.update(str.getBytes("UTF-8"));
			encodeStr = SecurityUtil.parseByte2HexStr(messageDigest.digest());
		} catch (NoSuchAlgorithmException e) {
			logger.error("SHA256Digest error.", e);
			throw e;
		} catch (UnsupportedEncodingException e) {
			logger.error("SHA256Digest error.", e);
			throw e;
		} catch(Exception e){
			logger.error("SHA256Digest error.", e);
			throw e;
		}
		if (upperCase) {
			encodeStr = encodeStr.toUpperCase();
		} else {
			encodeStr = encodeStr.toLowerCase();
		}
		return encodeStr;
	}
	
	/**
	 * SHA-1认证加密
	 * 
	 * @param str
	 * @param upperCase
	 * @return
	 * @throws Exception
	 */
	public static String SHA1(String str, boolean upperCase) throws Exception {
		if (str == null) {
			return "";
		}
		MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
		messageDigest.update(str.getBytes("UTF-8"));
		String encret = SecurityUtil.parseByte2HexStr(messageDigest.digest());
		if(encret == null){
			encret = "";
		}
		encret = encret.toLowerCase();
		if (upperCase) {
			encret = encret.toUpperCase();
		}
		return encret;
	}
	
	// ------------------------------算术校验和 ---------------------------//
	/**
	 * 校验和
	 * 
	 * @param msg 需要计算校验和的byte数组
	 * @param length 校验和位数
	 * @return 计算出的校验和数组
	*/
	public static byte[] SumCheck(byte[] msg, int offset, int sumLen) {
		long mSum = 0;
		byte[] mByte = new byte[sumLen];
		for(int i=0; i<sumLen; i++){
			mByte[i] = 0;
		}
		if(msg == null || msg.length == 0){
			return mByte;
		}
			
		//逐Byte添加位数和 
		for (int i=offset; i<msg.length; i++) {
			byte byteMsg = msg[i];
			long mNum = ((long)byteMsg >= 0) ? (long)byteMsg : ((long)byteMsg + 256);
			mSum += mNum;
		}
			
		//位数和转化为Byte数组 
		for (int liv_Count = 0; liv_Count < sumLen; liv_Count++) {
			mByte[sumLen - liv_Count - 1] = (byte)(mSum >> (liv_Count * 8) & 0xff);
		}
			
		return mByte;
	}
	
	/**
	 * 校验和
	 * 
	 * @param msg 需要计算校验和的byte数组
	 * @param length 校验和位数
	 * @return 计算出的校验和数组
	*/
	public static byte SumCheck(byte[] msg, int offset) {
		if(msg == null || msg.length == 0){
			return 0;
		}
		byte[] bs = SumCheck(msg, offset, 1);
		return bs[0];
	}
    
    // ---------------test-------------------------//   
	public static void main2(String[] args) throws Exception {
		if(false){
			byte[] b = new byte[7];
	        b[0] = (byte) 0xfd;
	        b[1] = (byte) 0xfc;
	        b[2] = (byte) 0x08;
	        b[3] = (byte) 0x80;
	        b[4] = (byte) 0x02;
	        b[5] = (byte) 0x00;
	        b[6] = (byte) 0x0a;
			byte[] sc = SumCheck(b, 0, 1);
			System.out.println("sc="+sc[0]);
			return;
		}
		
		if(false){
			// String aesSeeds = "ZTEClaa2017_xwfd";
			String content = "11223344556677889900112233445566adfaasfasdfasdfasdfasfasdfasdfasfasdfasfasdfasdfas";
			System.out.println("aesSeeds="+AES128_DEF_SEED_STR);
			System.out.println("原始明文:\n"+content);
			String enStr = AES128_CBC_PKCS5Pad_Encrypt(AES128_DEF_SEED_STR, content);
			System.out.println("After AESEncrypt: \n"+enStr);
			System.out.println("After AESDecrypt: \n"+AES128_CBC_PKCS5Pad_Decrypt(AES128_DEF_SEED_STR, enStr));
			// 循环加密和解密5000次，耗时212ms 
			/*
			long st = System.currentTimeMillis();
			for(int i=0; i<5000; i++){
				enStr = AESCbcEncrypt(content);
				AESCbcDecrypt(enStr);
			//System.out.println("After AESEncrypt2: \n"+enStr);
			//System.out.println("After AESDecrypt2: \n"+AESCbcDecrypt(enStr));
			}			
			System.out.println("usetime="+(System.currentTimeMillis()-st));
			*/
			return;
		}
		
		if (false) {
			String str = "AABBCCDDEEFF0011";
			System.out.println("str1: " + str);
			System.out.println("MD5: " + MD5(str));
			// System.out.println("MD5: "+MD5(str));
			str = "908711dd739c44e89f87b98f3b9c4557";
			System.out.println("str2: " + str);
			System.out.println("MD5: " + MD5(str));
			str = "";
			System.out.println("str3: " + str);
			System.out.println("MD5: " + MD5(str));
		}
		
		if(false){
			// m1-10000.csv
			String srcOrgFilePath = "D:\\m3-20.csv";
			String destEncryptFilePath = "D:\\zip\\m3-20.data";
			String destDecryptFilePath = "D:\\m3-20.decrypt";
			String md5FilePath = "D:\\zip\\m3-20.md5.txt";
			String zipFileDir = "D:\\zip123\\1.zip";
			File[] srcFiles = new File[]{new File("d:\\zip\\m3-20.data"), new File("d:\\zip\\m3-20.md5.txt")};
			try{
				String sContent = SecurityUtil.readFile(srcOrgFilePath);
				String encContent = SecurityUtil.AESCbcEncrypt(sContent);
				SecurityUtil.writeFile(encContent, destEncryptFilePath);
				String decContent = SecurityUtil.AESCbcDecrypt(encContent);
				SecurityUtil.writeFile(decContent, destDecryptFilePath);
				String md5Content = SecurityUtil.MD5(SecurityUtil.readFile(destEncryptFilePath));
				SecurityUtil.writeFile(md5Content, md5FilePath);
				ZipUtil.ZipFiles(zipFileDir, "", srcFiles);
				System.out.println("ok!");
			}catch(Exception e){
				e.printStackTrace();
			}			
			return;
		}
		
		// SHA-256
		if(false){
			String str = "123138012ladjlasfljfsdj4984534";
			System.out.println("SHA-256: src="+str);
			str = SHA256Digest(str, false);
			System.out.println("SHA-256: enc="+str);
			return;
		}
		
		
		byte[] bkeyarr = apacheBase64.decode("SivnBF2z0IY=");
		byte[] bivarr = apacheBase64.decode("uK1EBgjPTr0=");
		System.out.println("bkeyarr="+String.valueOf(bkeyarr)+", bivarr="+String.valueOf(bivarr));
		
		 String pass = "11";
		 // db 假如数据库密码为
		 String dbpass = "07ad04719525444cbd55807a98fcdfd3";
		
		 System.out.println(pass);
		 System.out.println(dbpass);
		 System.out.println("密码是否一致:" + pass.equals(dbpass));
		 System.out.println(encrypt("Claa2017"));
		 System.out.println(decrypt(encrypt("Claa2017")));
		 System.out.println("bkey="+String.valueOf(bkey)+", biv="+String.valueOf(biv));
		 
		// --------------------------- AES test -----------------------//
		System.out.println("-----------AES-128-ECB------------------"); 
		String cKey = "12345678901234561234567890123456"; 
        // 需要加密的字串
        String cSrc = "908711dd739c44e89f87b98f3b9c4557";
        String eui = "0200000000001211";
    	String kiid = "11223344";
        System.out.println(cSrc);
        // 加密
        String enString = Encrypt_AES_CMAC16(cSrc, cKey, eui, kiid);
        System.out.println("加密后的字串是：" + enString);
        // System.out.println("c9:00:12:a6:f6:55:3d:30:7f:d3:e4:ce:eb:0f:c3:3c".toUpperCase());

        // 解密
        String DeString = Decrypt_AES_CMAC16(enString, cKey, eui, kiid);
        System.out.println("解密后的字串是：" + DeString);
        
        // ------------3des -test -------------//
        System.out.println("-----------3DES-ECB------------------"); 
        byte[] key= "06111111FFFFFFFF06111111FFFFFFFF".getBytes("UTF-8"); 
        byte[] keyiv = { 1, 2, 3, 4, 5, 6, 7, 8 };            
        byte[] data="asldajslfajlsdjasldfjasldfjasldfjasldfjsale4oiodjlj3lhcvhiearakhksajfdaslj".getBytes("UTF-8");            
        System.out.println("ECB加密解密: asldajslfajlsdjasldfjasldfjasldfjasldfjsale4oiodjlj3lhcvhiearakhksajfdaslj");  
        byte[] str3 = des3EncodeECB(key, data );  
        byte[] str4 = des3DecodeECB(key,str3);  
        System.out.println(parseByte2HexStr(str3));  
        System.out.println(new String(str4, "UTF-8"));  
        System.out.println("----------3DES-CBC-------------------");  
        System.out.println("CBC加密解密: asldajslfajlsdjasldfjasldfjasldfjasldfjsale4oiodjlj3lhcvhiearakhksajfdaslj");  
        byte[] str5 = des3EncodeCBC(key, keyiv, data);  
        byte[] str6 = des3DecodeCBC(key, keyiv, str5);  
        System.out.println(parseByte2HexStr(str5));  
        System.out.println(new String(str6, "UTF-8"));  
        
	}
}